package com.mgg.user.service.shop.impl;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

import com.mgg.common.dao.DaoSupport;
import com.mgg.common.enums.UserRoleEnum;
import com.mgg.common.exception.ServiceException;
import com.mgg.common.util.DateUtils;
import com.mgg.common.util.ResultVOUtil;
import com.mgg.user.enums.UserResultEnum;
import com.mgg.user.service.shop.ShopService;
import com.mgg.user.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import com.alibaba.druid.util.StringUtils;
import com.github.pagehelper.PageHelper;

import javax.sql.rowset.serial.SerialException;

@Service("shopService")
public class ShopServiceImpl implements ShopService {
	
	@Autowired
	private DaoSupport dao;

	@Autowired
	private StringRedisTemplate redisTemplate;

    @Override
    public Boolean isMyLowerShop(Map<String, String> map) {
        Boolean isMyLowerShop = dao.findForObject("ShopMapper.isMyLowerShop", map);
        return isMyLowerShop;
    }

	@Override
	public Map<String, Object> getTutorStatistics(String userId, String shopCode) {
		Map<String,Object> result = new HashMap<>();
		//总销售额，累计收益，月销售额，月收益
		BigDecimal totalSalesAmount = getTotalSalesAmount(shopCode);
		BigDecimal monthSalesAmount = getMonthSalesAmount(shopCode);
		BigDecimal totalIncome = getTotalIncome(userId);
		BigDecimal monthIncome = getMonthIncome(userId);
		result.put("totalSalesAmount", totalSalesAmount);
		result.put("monthSalesAmount", monthSalesAmount);
		result.put("totalIncome", totalIncome);
		result.put("monthIncome", monthIncome);

		//会员人数
		result.put("memberNum", countMemberNum(userId));
		//推荐店主
		result.put("recdTutorNum", countRecdTutorNum(shopCode));

		return result;
	}

    @Override
    public BigDecimal getTotalSalesAmount(String shopCode) {
        BigDecimal salesAmount = countSalesAmountByShopCodeAndTime(shopCode,null,null,null,null,null);
        return salesAmount;
    }

    @Override
    public BigDecimal getMonthSalesAmount(String shopCode) {
        String month = DateUtils.getMonth(LocalDate.now());
        BigDecimal salesAmount = countSalesAmountByShopCodeAndTime(shopCode,month,null,null,null,null);
        return salesAmount;
    }

    private BigDecimal countSalesAmountByShopCodeAndTime(String shopCode, String month, String day, String startTime, String endTime, String orderType) {
        Map<String,String> queryMap = new HashMap<>();
        queryMap.put("shopCode",shopCode);
        queryMap.put("month",month);
        queryMap.put("day",day);
        queryMap.put("startTime",startTime);
        queryMap.put("endTime",endTime);
        queryMap.put("orderType", orderType);
        BigDecimal salesAmount = dao.findForObject("ShopMapper.countSalesAmountByShopCodeAndTime", queryMap);
        if (salesAmount.compareTo(new BigDecimal(0)) < 0) {
            salesAmount = new BigDecimal(0);
        }
        return salesAmount;
    }

    private BigDecimal countRefundAmountByShopCodeAndTime(String shopCode, String month, String day, String startTime, String endTime, String orderType) {
        Map<String,String> queryMap = new HashMap<>();
        queryMap.put("shopCode",shopCode);
        queryMap.put("month",month);
        queryMap.put("day",day);
        queryMap.put("startTime",startTime);
        queryMap.put("endTime",endTime);
        queryMap.put("orderType", orderType);
        BigDecimal amount = dao.findForObject("ShopMapper.countRefundAmountByShopCodeAndTime", queryMap);
        if (amount.compareTo(new BigDecimal(0)) < 0) {
            amount = new BigDecimal(0);
        }
        return amount;
    }

    @Override
    public BigDecimal getTotalIncome(String userId ) {
        BigDecimal income = countIncomeByUserIdAndTime(userId,null,null,null,null,null);
        return income;
    }

    @Override
    public BigDecimal getMonthIncome(String userId ) {
        String month = DateUtils.getMonth(LocalDate.now());
        BigDecimal income = countIncomeByUserIdAndTime(userId,month,null,null,null,null);
        return income;
    }

    @Override
    public BigDecimal getTodayIncome(String userId ) {
        String day = DateUtils.getDay();
        BigDecimal income = countIncomeByUserIdAndTime(userId,null,day,null,null,null);
        return income;
    }

    private BigDecimal countIncomeByUserIdAndTime(String userId, String month, String day, String startTime, String endTime, String type) {
        Map<String,String> queryMap = new HashMap<>();
        queryMap.put("userId",userId);
        queryMap.put("month",month);
        queryMap.put("day",day);
        queryMap.put("startTime",startTime);
        queryMap.put("endTime",endTime);
        queryMap.put("type", type);
        BigDecimal income = dao.findForObject("ShopMapper.countIncomeByUserIdAndTime", queryMap);
        if (income.compareTo(new BigDecimal(0)) < 0) {
            income = new BigDecimal(0);
        }
        return income;
    }

    @Override
    public Integer getTodayOrderNum(String shopCode) {
	    String day = DateUtils.getDay();
	    Integer orderNum = countOrderNumByShopCodeAndTime(shopCode,null,day,null,null);
        return orderNum;
    }

    private Integer countOrderNumByShopCodeAndTime(String shopCode, String month, String day, String startTime, String endTime) {
        Map<String,String> queryMap = new HashMap<>();
        queryMap.put("shopCode",shopCode);
        queryMap.put("month",month);
        queryMap.put("day",day);
        queryMap.put("startTime",startTime);
        queryMap.put("endTime",endTime);
        Integer orderNum = dao.findForObject("ShopMapper.countOrderNumByShopCodeAndTime", queryMap);
        return orderNum;
    }

    @Override
    public Integer countMemberNum(String userId) {
        Map<String, Object> queryMap = new HashMap<>();
        Integer memberNum = dao.findForObject("ShopMapper.countMemberNum", userId);
        return memberNum;
    }

    @Override
    public List<UserSimpleVO> listMember(String userId, Pageable page) {
        PageHelper.startPage(page.getPageNumber(), page.getPageSize());
        List<UserSimpleVO> userSimpleVOList = new ArrayList<>();
        List<UserInfoVO> userInfoVOList = dao.findForList("ShopMapper.listMemberInfo", userId);
        for (UserInfoVO userInfoVO : userInfoVOList) {
            UserSimpleVO userSimpleVO = new UserSimpleVO();
            userSimpleVO.setAddtime(userInfoVO.getAddtime());
            userSimpleVO.setHeadImg(userInfoVO.getHeadImg());
            userSimpleVO.setSex(userInfoVO.getSex());
            if (!StringUtils.isEmpty(userInfoVO.getRealName())) {
                userSimpleVO.setUsername(userInfoVO.getUsername() + "(" + userInfoVO.getRealName() +")");
            } else {
                userSimpleVO.setUsername(userInfoVO.getUsername());
            }
            if (!StringUtils.isEmpty(userInfoVO.getPhone())) {
                userSimpleVO.setPhone(userInfoVO.getPhone().replaceAll("(?<=[\\d]{3})\\d(?=[\\d]{4})", "*"));
            }
            userSimpleVOList.add(userSimpleVO);
        }
        return userSimpleVOList;
    }

	@Override
	public void visitShop(String shopCode) {
		String key = "shop:" + shopCode + ":today:visitNum";
		if (!redisTemplate.hasKey(key)) {
			DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
			LocalDateTime nowtime = LocalDateTime.now();
			String endtimeString = nowtime.format(df).split(" ")[0] + " 23:59:59";
			LocalDateTime endtime = LocalDateTime.parse(endtimeString, df);
			Duration duration = Duration.between(nowtime, endtime);
			redisTemplate.opsForValue().set(key, "1", duration.toMillis(), TimeUnit.MILLISECONDS);
		} else {
			Integer todayViewNum = Integer.parseInt(redisTemplate.opsForValue().get(key)) + 1;
			redisTemplate.opsForValue().set(key, todayViewNum.toString(), redisTemplate.getExpire(key), TimeUnit.SECONDS);
		}
	}
	
	@Override
	public Integer getTodayVisitNum(String shopCode) {
        Integer todayViewNum = 0;
		String key = "shop:" + shopCode + ":today:visitNum";
		String value = redisTemplate.opsForValue().get(key);
		if (!StringUtils.isEmpty(value)) {
			todayViewNum = Integer.parseInt(value);
		}
		return todayViewNum;
	}

    @Override
    public Map<String, Object> getShopSalesCount(String shopCode, String roleCode) {
        Map<String,Object> result = new HashMap<>();
        Map<String,Object> salesCountMap = (Map<String, Object>) dao.findForObject("ShopMapper.getShopSalesCount", shopCode);
        result.putAll(salesCountMap);

        Map<String,Object> salesTargetMap = new HashMap<>();
        if (UserRoleEnum.TUTOR.getCode().equals(roleCode) || UserRoleEnum.MANAGER.getCode().equals(roleCode)) {
            salesTargetMap = (Map<String, Object>) dao.findForObject("ShopMapper.getUserUpgradeSales", Integer.parseInt(roleCode) + 1);
            result.putAll(salesTargetMap);
        } else if(UserRoleEnum.DIRECTOR.getCode().equals(roleCode)) {
            salesTargetMap = (Map<String, Object>) dao.findForObject("ShopMapper.getUserUpgradeSales", Integer.parseInt(roleCode));
        } else {
            salesTargetMap.put("sgift_sale",0);
            salesTargetMap.put("sgoods_sale",0);
        }
        result.putAll(salesTargetMap);
        return result;
    }

    @Override
    public Integer countRecdTutorNum(String shopCode) {
        return dao.findForObject("ShopMapper.countRecdTutorNum", shopCode);
    }

    @Override
    public Integer countDirectRecdTutorNum(String shopCode) {
        return dao.findForObject("ShopMapper.countDirectRecdTutorNum", shopCode);
    }

    @Override
    public List<RecdUserVO> listRecdShopkeeper(String shopCode, Pageable page) {
        PageHelper.startPage(page.getPageNumber(), page.getPageSize());
        List<RecdUserVO> userList = dao.findForList("ShopMapper.listRecdShopkeeper", shopCode);
        return userList;
    }

    @Override
    public Map<String, Object> getCommunityInfo(String userId, String roleCode) {
        if (UserRoleEnum.MANAGER.getCode().equals(roleCode)) {
            return getMangerCommunityInfo(userId);
        } else if (UserRoleEnum.DIRECTOR.getCode().equals(roleCode)) {
            return getDirectorCommunityInfo(userId);
        } else {
            throw new ServiceException(UserResultEnum.ACCESS_DENIED.getCode(), UserResultEnum.ACCESS_DENIED.getMessage());
        }
    }

    public Map<String, Object> getDirectorCommunityInfo(String userId) {
        Map<String,Object> result = new HashMap<>();
        // 店主数
        int tutorNum = dao.findForObject("ShopMapper.countCommunityTutorNum", userId);
        // 经理数
        int managerNum = dao.findForObject("ShopMapper.countCommunityManagerNum", userId);
        // 我的店主数
        int myTutorNum = dao.findForObject("ShopMapper.countMyTutorNum", userId);
        result.put("memberNum", managerNum + tutorNum + 1);
        result.put("managerNum", managerNum);
        result.put("tutorNum", tutorNum);
        result.put("myTutorNum", myTutorNum);
        return result;
    }

    public Map<String, Object> getMangerCommunityInfo(String userId) {
        Map<String,Object> result = new HashMap<>();
        // 店主数
        int tutorNum = dao.findForObject("ShopMapper.countMyTutorNum", userId);
        result.put("memberNum", tutorNum + 1);
        result.put("memberNumName", "社群人数");
        result.put("tutorNum", tutorNum);
        result.put("tutorNumName", "社群店主");
        result.put("managerNum", 1);
        result.put("managerNumName", "培训经理(自己)");
        return result;
    }


    @Override
    public List<TutorVO> listCommunityDirectTutor(String userId, String shopCode, Pageable page) {
        PageHelper.startPage(page.getPageNumber(), page.getPageSize());
        List<TutorVO> tutorVOList = dao.findForList("ShopMapper.listMyTutor", userId);
        return tutorVOList;
    }

    @Override
    public List<ManagerVO> listCommunityDirectManage(String userId, String shopCode, Pageable page){
        PageHelper.startPage(page.getPageNumber(), page.getPageSize());
        List<ManagerVO> managerVOList = dao.findForList("ShopMapper.listMyManager", userId);
        return managerVOList;
    }

	/**
	 * 社群业绩统计
	 */
	@Override
	public Map<String, Object> getCommunityAchievement(String userId, String shopCode) {
        List<Map<String,String>> teamList = listTeamUserIdAndShopCode(userId);
        // 商品销售累计销售额
        BigDecimal goodsSalesAmount = new BigDecimal(0);
        // 开店礼包累计销售额
        BigDecimal giftSalesAmount = new BigDecimal(0);
        // 商品销售累计收益
        BigDecimal goodsSalesIncome = new BigDecimal(0);
        // 开店礼包累计收益
        BigDecimal giftSalesIncome = new BigDecimal(0);
        for (Map<String,String> userMap : teamList) {
            String teamShopCode = userMap.get("shop_code");
            String teamUserId = userMap.get("user_id");
            goodsSalesAmount = goodsSalesAmount.add(countSalesAmountByShopCodeAndTime(teamShopCode,null,null,null,null,"0"));
            giftSalesAmount = giftSalesAmount.add(countSalesAmountByShopCodeAndTime(teamShopCode,null,null,null,null,"5"));
            goodsSalesIncome = goodsSalesIncome.add(countIncomeByUserIdAndTime(teamUserId,null,null,null,null,"1"));
            giftSalesIncome = giftSalesIncome.add(countIncomeByUserIdAndTime(teamUserId,null,null,null,null,"2"));
        }
		// 累计销售额
		BigDecimal totalSalesAmount = giftSalesAmount.add(goodsSalesAmount);
		// 累计收益
		BigDecimal totalSalesIncome = giftSalesIncome.add(goodsSalesIncome);

		//前3个月销售统计
		LocalDate date = LocalDate.now();
		List<Map<String,Object>> monthSalesCountList = new ArrayList<>();
		for (int i = 0; i <= 2; i++) {
			Map<String,Object> count = getCommunityAchievementByMonth(teamList, DateUtils.getMonth(date.minusMonths(i)));
			monthSalesCountList.add(count);
		}

		Map<String,Object> result = new HashMap<>();
		result.put("giftSalesAmount", giftSalesAmount);
		result.put("goodsSalesAmount", goodsSalesAmount);
		result.put("totalSalesAmount", totalSalesAmount);
		result.put("giftSalesIncome", giftSalesIncome);
		result.put("goodsSalesIncome", goodsSalesIncome);
		result.put("totalSalesIncome", totalSalesIncome);
		result.put("monthSalesCountList", monthSalesCountList);
		return result;
	}

	private List<Map<String,String>> listTeamUserIdAndShopCode(String userId) {
        List<Map<String,String>> teamList = dao.findForList("ShopMapper.listTeamUserIdAndShopCode", userId);
        return teamList;
    }

	/**
	 * 根据月份获取社群业绩销售统计
	 * @param teamList
	 * @param month
	 * @return
	 * @throws Exception
	 */
	private Map<String, Object> getCommunityAchievementByMonth(List<Map<String,String>> teamList, String month) {
        //本月销售订单数
        Integer monthSalesNum = 0;
        //本月退款总额
        BigDecimal monthSalesRefund = new BigDecimal(0);
        // 本月净销售额
        BigDecimal monthSalesAmount = new BigDecimal(0);
        // 本月销售收益
        BigDecimal monthSalesIncome = new BigDecimal(0);

        for (Map<String,String> userMap : teamList) {
            String teamShopCode = userMap.get("shop_code");
            String teamUserId = userMap.get("user_id");
            monthSalesNum = monthSalesNum + countOrderNumByShopCodeAndTime(teamShopCode,null,null,null,null);
            monthSalesRefund = monthSalesRefund.add(countRefundAmountByShopCodeAndTime(teamShopCode,month,null,null,null,null));
            monthSalesAmount = monthSalesAmount.add(countSalesAmountByShopCodeAndTime(teamShopCode,month,null,null,null,null));
            monthSalesIncome = monthSalesIncome.add(countIncomeByUserIdAndTime(teamUserId,month,null,null,null,null));
        }
		Map<String,Object> result = new HashMap<>();
		result.put("num", monthSalesNum);
		result.put("income", monthSalesIncome);
		result.put("amount", monthSalesAmount);
		result.put("refund", monthSalesRefund);	
		result.put("sales", monthSalesAmount.add(monthSalesRefund));	
		result.put("month", month);
		return result;
	}
	

	/**
	 * 社群销售明细
	 */
	@Override
	public List<ManagerAchievementVO> listCommunityAchievement(String userId, String shopCode, String month, Pageable page) {
        PageHelper.startPage(page.getPageNumber(), page.getPageSize());
		Map<String,Object> map = new HashMap<>();
		map.put("userId", userId);
		map.put("shopCode", shopCode);	
		map.put("startTime", DateUtils.getFirstDayOfMonth(month));
		map.put("endTime",DateUtils.getLastDayOfMonth(month));
        List<Map<String,String>> teamList = listTeamUserIdAndShopCode(userId);
        map.put("teamList",teamList);
		List<ManagerAchievementVO> monthIncomeList = dao.findForList("ShopMapper.listTeamSalesOrderByTime", map);
		return monthIncomeList;
	}
}
